/**
 * @file hc_sr04.c
 * @brief 超声波测距模块
 * @details 该模块通过GPIO控制超声波模块的触发信号，
 *          同时通过GPIO读取超声波模块的回响信号。
 *          精度3mm, 量程2cm-400cm, 返回的距离单位为cm。
 * @version 0.1
 * @date 2025-06-05
 */
#include "hc_sr04.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>

uint32_t cnt_hc_sr04 = 0;

void hc_sr04_init(void) {
    rcu_periph_clock_enable(ECHO_RCU);
    rcu_periph_clock_enable(TRIG_RCU);

    gpio_mode_set(ECHO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, ECHO_PIN);
    gpio_mode_set(TRIG_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TRIG_PIN);

    gpio_output_options_set(TRIG_PIN, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, TRIG_PIN);
    gpio_bit_reset(TRIG_PORT, TRIG_PIN);
}

static float hc_sr04_get(void) {
    // Trigger
    gpio_bit_set(TRIG_PORT, TRIG_PIN);
    delay_1us(20);
    gpio_bit_reset(TRIG_PORT, TRIG_PIN);

    // Wait echo pin high
    while (RESET == gpio_input_bit_get(ECHO_PORT, ECHO_PIN));
    cnt_hc_sr04 = 0;

    // Count time for echo pin high
    while (SET == gpio_input_bit_get(ECHO_PORT, ECHO_PIN)){
        delay_1us(1);
        cnt_hc_sr04++;
    }

    // Calculate distance
    float dis = cnt_hc_sr04 / 58.0f;
    if (dis > 400) return 400.0f;
    if (dis < 2) return 2.0f;
    return dis;
}

/**
 * @brief 获取距离，单位cm，从传入距离指针修改距离的值
 * 
 * @param pvDistance 
 */
void fGetDistance(void* pvDistance){
    while(1){
        *(float*)pvDistance = hc_sr04_get();
        // printf("Distance is %5.1f cm.\r\n", *(float*)pvDistance);
        vTaskDelay(95);
    }
}
